package itsm.isperp.module.service.app;

import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.sequence.SequenceService;
import itsm.isperp.framework.service.BaseService;
import itsm.isperp.framework.utils.HibernateUUIDGenerator;
import itsm.isperp.module.entity.app.AppSequence;
import itsm.isperp.module.repository.app.AppSequenceMapper;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 系统流水号服务
 * 
 * @author lizx
 * @date 2013-2-17
 * @version V1.0
 */
@Service
public class AppSequenceService extends BaseService<AppSequence> implements
		SequenceService {

	@Autowired
	protected AppSequenceMapper appSequenceMapper;

	@Override
	public AppSequenceMapper getRepository() {
		return this.appSequenceMapper;
	}

	@Override
	public int saveOrUpdate(AppSequence entity, HttpServletRequest req) {

		if (StringUtils.isEmpty(entity.getName())) {
			throw new NullArgumentException("表明不能为空");
		}

		AppSequence seq = this.appSequenceMapper.findByTableName(entity
				.getName());

		if (seq != null) {
			throw new RuntimeException("重复的数据表名");
		}

		if (StringUtils.isEmpty(entity.getId())) {
			entity.setId(HibernateUUIDGenerator.generate().toString());

			this.getRepository().save(entity);
		} else {
			super.saveOrUpdateAndSpecific(entity, req);
		}

		ContextHolder.rebuildSeqRlue();
		return 1;
	}

	@Override
	public AppSequence findByTableName(String tableName) {
		return this.appSequenceMapper.findByTableName(tableName);
	}

	/**
	 * 
	 */
	@Override
	public synchronized long nextNumber(String tableName, Integer seqResetType) {

		// 得到流水号的一些设定数据

		Map<String, AppSequence> seqs = ContextHolder
				.getApplicationSequenceCache();

		AppSequence seq = seqs.get(tableName);

		Date now = new Date();
		Calendar nowC = Calendar.getInstance();
		nowC.setTime(now);

		Date lastSeqDate = seq.getLastSeqDate();
		Calendar lastSeqDateC = Calendar.getInstance();
		if (lastSeqDate == null) {
			lastSeqDate = new Date();
			seq.setLastSeqDate(new Date());
			lastSeqDate = seq.getLastSeqDate();
		}
		lastSeqDateC.setTime(lastSeqDate);

		switch (seq.getSeqResetType()) {
		case 1:
			// year
			if (nowC.get(Calendar.YEAR) != lastSeqDateC.get(Calendar.YEAR)) {
				seq.setSeqNumber(1);
			} else {
				seq.setSeqNumber(seq.getSeqNumber() + 1);
			}

			break;
		case 2:

			if (nowC.get(Calendar.YEAR) != lastSeqDateC.get(Calendar.YEAR)
					|| nowC.get(Calendar.MONTH) != lastSeqDateC
							.get(Calendar.MONTH)) {
				seq.setSeqNumber(1);
			} else {
				seq.setSeqNumber(seq.getSeqNumber() + 1);
			}
			break;
		case 3:
			if (nowC.get(Calendar.YEAR) != lastSeqDateC.get(Calendar.YEAR)
					|| nowC.get(Calendar.MONTH) != lastSeqDateC
							.get(Calendar.MONTH)
					|| nowC.get(Calendar.DAY_OF_MONTH) != lastSeqDateC

					.get(Calendar.DAY_OF_MONTH)) {
				seq.setSeqNumber(1);
			} else {
				seq.setSeqNumber(seq.getSeqNumber() + 1);
			}

			break;

		default:
			throw new RuntimeException("not support reset type!");
		}

		seq.setLastSeqDate(now);
		this.appSequenceMapper.updateSeqNumber(tableName, now,
				seq.getSeqNumber());
		return seq.getSeqNumber();

	}
}
